package org.bspv.pharma.message.template.impl;

import java.io.Serializable;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.RuntimeSingleton;
import org.apache.velocity.runtime.parser.node.SimpleNode;
import org.bspv.pharma.common.exception.TechnicalException;
import org.bspv.pharma.message.template.TemplateTechnicalService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.velocity.VelocityEngineUtils;

@Service(value = "templateTechService")
public class TemplateTechnicalServiceImpl implements TemplateTechnicalService {

    /**
     * LOGGER.
     */
    private static final Log LOGGER = LogFactory.getLog(TemplateTechnicalServiceImpl.class);
    /**
     * Moteur velocity.
     */
    @Autowired
    private VelocityEngine velocityEngine;

    /**
     * Encodage du template.
     */
    private String templateEncoding = "UTF-8";

    /**
     * @param templateEncoding
     *            the templateEncoding to set
     */
    public final void setTemplateEncoding(String templateEncoding) {
        this.templateEncoding = templateEncoding;
    }

    /**
     * @see TemplateTechnicalService.nantesmetropole.common.utils.template.TemplateTechService#generateTextContent(java.lang.String,
     *      java.util.Map)
     */
    @Override
    public String generateTextContent(String template, Map<String, Serializable> dataModel) throws TechnicalException {
        String contenuTexte = null;

        LOGGER.debug("Debut du service de generation de contenu texte");

        if (template == null) {
            throw new TechnicalException("Impossible de generer un contenu texte de template 'null'");
        }

        if (dataModel == null) {
            throw new TechnicalException("Impossible de generer un contenu texte de donnees 'null'");
        }

        try {

            contenuTexte = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, template, templateEncoding,
                    dataModel);
        } catch (Exception erreur) {
            LOGGER.error("Erreur du service de generation de contenu texte", erreur);
            throw new TechnicalException(erreur);
        }

        return contenuTexte;
    }

    /**
     * @see TemplateTechnicalService.nantesmetropole.common.utils.template.TemplateTechService#generateTextContentFromStringTemplate(java.lang.String,
     *      java.util.Map)
     */
    @Override
    public String generateTextContentFromStringTemplate(String templateContent, Map<String, Serializable> dataModel)
            throws TechnicalException {

        String generatedContent = null;

        if (templateContent == null) {
            String errorMessage = "The template content must be not null";
            LOGGER.error(errorMessage);
            throw new TechnicalException(errorMessage);
        }

        if (dataModel == null) {
            String errorMessage = "The data model content must be not null";
            LOGGER.error(errorMessage);
            throw new TechnicalException(errorMessage);
        }

        try {

            // Génération d'un nom de template temporaire
            String templateName = "Template" + System.currentTimeMillis();

            RuntimeServices runtimeServices = RuntimeSingleton.getRuntimeServices();
            StringReader reader = new StringReader(templateContent);
            SimpleNode node = runtimeServices.parse(reader, templateName);

            Template template = new Template();
            template.setRuntimeServices(runtimeServices);
            template.setData(node);
            template.initDocument();

            StringWriter writer = new StringWriter();
            VelocityContext velocityContext = new VelocityContext(dataModel);
            template.merge(velocityContext, writer);
            generatedContent = writer.toString();
        } catch (Exception e) {
            String errorMessage = "Error while generating content for " + templateContent;
            LOGGER.error(errorMessage, e);
            throw new TechnicalException(errorMessage, e);
        }

        return generatedContent;
    }

    /**
     * @return the velocityEngine
     */
    public final VelocityEngine getVelocityEngine() {
        return velocityEngine;
    }

    /**
     * @param velocityEngine
     *            the velocityEngine to set
     */
    public final void setVelocityEngine(VelocityEngine velocityEngine) {
        this.velocityEngine = velocityEngine;
        this.velocityEngine.setProperty("input.encoding", "UTF-8");
        this.velocityEngine.setProperty("output.encoding", "UTF-8");
    }

}
